package org.activiti.explorer.servlet.dispatcher;

import java.util.List;

import javax.servlet.ServletContext;

import org.activiti.explorer.filter.ExplorerFilter;
import org.activiti.rest.service.api.PutAwareCommonsMultipartResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import com.fasterxml.jackson.databind.ObjectMapper;

//@Configuration
//@ComponentScan({
//    "org.activiti.rest.service",
//    "org.activiti.rest.service.api",
//    "org.activiti.rest.exception", 
//    })
//@EnableAsync
public class DispatcherServletConfiguration extends WebMvcConfigurationSupport {

  private final Logger log = LoggerFactory.getLogger(DispatcherServletConfiguration.class);

  @Autowired
  private ObjectMapper objectMapper;
  
  @Autowired
  private Environment environment;

  @Bean
  public SessionLocaleResolver localeResolver() {
    return new SessionLocaleResolver();
  }

  @Bean
  public LocaleChangeInterceptor localeChangeInterceptor() {
    log.debug("Configuring localeChangeInterceptor");
    LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
    localeChangeInterceptor.setParamName("language");
    return localeChangeInterceptor;
  }

  @Bean
  public MultipartResolver multipartResolver() {
    PutAwareCommonsMultipartResolver multipartResolver = new PutAwareCommonsMultipartResolver();
    return multipartResolver;
  }

  @Bean
  public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    log.debug("Creating requestMappingHandlerMapping");
    RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
    requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
    Object[] interceptors = {localeChangeInterceptor()};
    requestMappingHandlerMapping.setInterceptors(interceptors);
    return requestMappingHandlerMapping;
  }

  @Bean
  public ServletRegistrationBean servletRegistration(DispatcherServlet dispatcherServlet){
      ServletRegistrationBean bean = new ServletRegistrationBean(dispatcherServlet);
      //bean.getUrlMappings().clear(); //后续需要考虑是否需要清理
      bean.addUrlMappings("/service/*");
      //bean.addUrlMappings("/*");
      bean.setLoadOnStartup(1);
      bean.setAsyncSupported(true);
      servletContext();
      return bean;
  }

  public ServletContext servletContext(){
      ServletContext servletContext = getServletContext();
      //servletContext.addFilter("/activiti-explorer/*", ExplorerFilter.class);
      servletContext.addFilter("/*", ExplorerFilter.class);
      //servletContext.addFilter("/service/*", JsonpCallbackFilter.class);
      servletContext.addListener(RequestContextListener.class);
      //servletContext.addListener(WebConfigurer.class);
      return servletContext;
  }

//  @Bean
//  public FilterRegistrationBean filterRegistration(DispatcherServlet dispatcherServlet){
//      FilterRegistrationBean bean = new FilterRegistrationBean();
//      bean.setFilter(new ExplorerFilter());
//      bean.addUrlPatterns("/activiti-explorer/*");
//      bean.addServletRegistrationBeans(new ServletRegistrationBean(dispatcherServlet));
//      return bean;
//  }
  
//  @Bean
//  public ServletListenerRegistrationBean<EventListener> listenerRegistration(){
//      ServletListenerRegistrationBean<EventListener> bean = new ServletListenerRegistrationBean<>();
//      bean.setListener(new RequestContextListener());
//      return bean; 
//  }

//  @Bean
//  public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration(){
//      ServletListenerRegistrationBean<RequestContextListener> bean = 
//              new ServletListenerRegistrationBean<RequestContextListener>();
//      bean.setListener(new RequestContextListener());
//      return bean;
//  }

//  @Bean(name="ExplorerApplicationServlet")
//  public ServletRegistrationBean explorerApplicationServlet(){
//      ServletRegistrationBean bean = new ServletRegistrationBean();
//      bean.setName("ExplorerApplicationServlet");
//      bean.setServlet(new ExplorerApplicationServlet());
//      bean.addUrlMappings("/ui/*","/VAADIN/*");
//      bean.addInitParameter("widgetset", "org.activiti.explorer.CustomWidgetset");
//      return bean;
//  }

//  @Bean(name="ModelerServlet")
//  public ServletRegistrationBean modelerServlet(){
//      ServletRegistrationBean bean = new ServletRegistrationBean();
//      bean.setName("ModelerServlet");
//      bean.setServlet(new DispatcherServlet());
//      bean.addUrlMappings("/service/*");
//      return bean;
//  }

//  @Bean(name="RestServlet")
//  public ServletRegistrationBean restServlet(){
//      ServletRegistrationBean bean = new ServletRegistrationBean();
//      bean.setName("RestServlet");
//      bean.setServlet(new DispatcherServlet());
//      bean.addUrlMappings("/rest/*");
//      return bean;
//  }

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    addDefaultHttpMessageConverters(converters);
    for (HttpMessageConverter<?> converter: converters) {
      if (converter instanceof MappingJackson2HttpMessageConverter) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        break;
      }
    }
  }

  @Override
  protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(false);
  }
  
}
